home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Examples / Printer / HP_DeskJet_CMYK / transfer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-30  |  19.0 KB  |  746 lines

  1. /*
  2.  * $Id: transfer.c 44.6 1999/09/17 19:03:43 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * COPYRIGHT:
  7.  *
  8.  *   Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
  9.  *   All rights reserved.
  10.  *
  11.  * DISCLAIMER:
  12.  *
  13.  *   This software is provided "as is". No representations or warranties
  14.  *   are made with respect to the accuracy, reliability, performance,
  15.  *   currentness, or operation of this software, and all use is at your
  16.  *   own risk. Neither Amiga nor the authors assume any responsibility
  17.  *   or liability whatsoever with respect to your use of this software.
  18.  *
  19.  */
  20.  
  21. #include "global.h"
  22.  
  23. /****************************************************************************/
  24.  
  25. /* Parameters of a pseudo-random-number generator from Knuth's
  26.  * "The Art of Computer Programming, Volume 2: Seminumerical
  27.  *  Algorithms" (3rd edition). We need a generator with a large
  28.  * repeat cycle to avoid introducing artefacts into the dithering
  29.  * process.
  30.  */
  31.  
  32. #define MM 2147483647    /* a Mersenne prime */
  33. #define AA 48271        /* this does well in the spectral test */
  34. #define QQ 44488        /* (long)(MM/AA) */
  35. #define RR 3399            /* MM % AA; it is important that RR < QQ */
  36.  
  37. /****************************************************************************/
  38.  
  39. DITHERDATA_T *
  40. CreateDitherData(LONG samplesPerLine,LONG numLines,LONG pad)
  41. {
  42.     DITHERDATA_T * result = NULL;
  43.     DITHERDATA_T * dd;
  44.  
  45.     dd = AllocVec(sizeof(*dd) +
  46.                   numLines * sizeof(SAMPLE_T *) +
  47.                   numLines * (pad + samplesPerLine + pad) * sizeof(SAMPLE_T),
  48.                   MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  49.  
  50.     if(dd != NULL)
  51.     {
  52.         LONG i;
  53.  
  54.         dd->dd_SamplesPerLine    = samplesPerLine;
  55.         dd->dd_NumLines            = numLines;
  56.         dd->dd_Lines            = (SAMPLE_T **)(dd + 1);
  57.  
  58.         dd->dd_Lines[0] = (SAMPLE_T *)&dd->dd_Lines[numLines];
  59.  
  60.         for(i = 1 ; i < numLines ; i++)
  61.             dd->dd_Lines[i] = dd->dd_Lines[i-1] + (pad + samplesPerLine + pad);
  62.  
  63.         for(i = 0 ; i < numLines ; i++)
  64.             dd->dd_Lines[i] += pad;
  65.  
  66.         /* Use the address of the line as the seed for our
  67.          * pseudo-random-number generator.
  68.          */
  69.         dd->dd_Seed = (LONG)dd;
  70.  
  71.         result = dd;
  72.     }
  73.  
  74.     return(result);
  75. }
  76.  
  77. VOID
  78. DeleteDitherData(DITHERDATA_T * dd)
  79. {
  80.     FreeVec(dd);
  81. }
  82.  
  83. /****************************************************************************/
  84.  
  85. STATIC VOID
  86. RotateDitherLines(DITHERDATA_T * dd)
  87. {
  88.     SAMPLE_T * swap;
  89.     LONG i;
  90.  
  91.     swap = dd->dd_Lines[0];
  92.  
  93.     for(i = 0 ; i < dd->dd_NumLines-1 ; i++)
  94.         dd->dd_Lines[i] = dd->dd_Lines[i+1];
  95.  
  96.     dd->dd_Lines[dd->dd_NumLines-1] = swap;
  97.  
  98.     memset(dd->dd_Lines[dd->dd_NumLines-1],0,sizeof(SAMPLE_T) * dd->dd_SamplesPerLine);
  99.  
  100.     dd->dd_Reverse ^= TRUE;
  101. }
  102.  
  103. /****************************************************************************/
  104.  
  105. STATIC VOID
  106. TransferBlueNoise(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,DITHERDATA_T * dd)
  107. {
  108.     SAMPLE_T threshold,error,e1,e3,e5,e7,weight,err2;
  109.     SAMPLE_T * this = dd->dd_Lines[0];
  110.     SAMPLE_T * next = dd->dd_Lines[1];
  111.     LONG X = dd->dd_Seed;
  112.     LONG x;
  113.  
  114.     if(dd->dd_Reverse)
  115.     {
  116.         ColorInt += (width-1);
  117.  
  118.         for(x = width-1 ; x >= 0 ; x--)
  119.         {
  120.             /* Add the intensity (the greater the darker) and the error for
  121.              * the current line.
  122.              */
  123.             threshold = (this[x] / 16) + ColorInt->colorByte[component];
  124.  
  125.             /* Make sure that the resulting value is within
  126.              * valid bounds.
  127.              */
  128.             if(threshold < 0)
  129.                 threshold = 0;
  130.             else if (threshold > 255)
  131.                 threshold = 255;
  132.  
  133.             ColorInt--; /* bump ptr for next time */
  134.  
  135.             /* Now check if this pixel should come out black
  136.              * or white (0 = white, 255 = black).
  137.              */
  138.             if(threshold < 128)
  139.             {
  140.                 /* White pixel */
  141.                 error = threshold - 0;
  142.             }
  143.             else
  144.             {
  145.                 /* Black pixel */
  146.                 error = threshold - 255;
  147.  
  148.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  149.             }
  150.  
  151.             /* Now distribute the error. */
  152.             err2 = error + error;
  153.  
  154.                             e1 = error;
  155.             error += err2;    e3 = error;
  156.             error += err2;    e5 = error;
  157.             error += err2;    e7 = error;
  158.  
  159.             /* Crank out another pseudo random number... */
  160.             X = AA * (X % QQ) - RR * (LONG)(X / QQ);
  161.             if(X < 0)
  162.                 X += MM;
  163.  
  164.             /* Calculate the random weight. */
  165.             weight = X % max(1,min(e5,e7));
  166.  
  167.             /* Skew the large errors with the weight. */
  168.             e5 -=           weight/2;
  169.             e7 += weight - (weight/2);
  170.  
  171.             /* Crank out another pseudo random number... */
  172.             X = AA * (X % QQ) - RR * (LONG)(X / QQ);
  173.             if(X < 0)
  174.                 X += MM;
  175.  
  176.             /* Calculate the random weight. */
  177.             weight = X % max(1,min(e1,e3));
  178.  
  179.             /* Skew the small errors with the weight. */
  180.             e1 -=           weight/2;
  181.             e3 += weight - (weight/2);
  182.  
  183.             next[x-1] += e1;    /* 1 x error */
  184.             next[x+1] += e3;    /* 3 x error */
  185.             next[x  ] += e5;    /* 5 x error */
  186.             this[x-1] += e7;    /* 7 x error */
  187.         }
  188.     }
  189.     else
  190.     {
  191.         for(x = 0 ; x < width ; x++)
  192.         {
  193.             /* Add the intensity (the greater the darker) and the error for
  194.              * the current line.
  195.              */
  196.             threshold = (this[x] / 16) + ColorInt->colorByte[component];
  197.  
  198.             /* Make sure that the resulting value is within
  199.              * valid bounds.
  200.              */
  201.             if(threshold < 0)
  202.                 threshold = 0;
  203.             else if (threshold > 255)
  204.                 threshold = 255;
  205.  
  206.             ColorInt++; /* bump ptr for next time */
  207.  
  208.             /* Now check if this pixel should come out black
  209.              * or white (0 = white, 255 = black).
  210.              */
  211.             if(threshold < 128)
  212.             {
  213.                 /* White pixel */
  214.                 error = threshold - 0;
  215.             }
  216.             else
  217.             {
  218.                 /* Black pixel */
  219.                 error = threshold - 255;
  220.  
  221.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  222.             }
  223.  
  224.             /* Now distribute the error. */
  225.             err2 = error + error;
  226.  
  227.                             e1 = error;
  228.             error += err2;    e3 = error;
  229.             error += err2;    e5 = error;
  230.             error += err2;    e7 = error;
  231.  
  232.             /* Crank out another pseudo random number... */
  233.             X = AA * (X % QQ) - RR * (LONG)(X / QQ);
  234.             if(X < 0)
  235.                 X += MM;
  236.  
  237.             /* Calculate the random weight. */
  238.             weight = X % max(1,min(e5,e7));
  239.  
  240.             /* Skew the large errors with the weight. */
  241.             e5 -=           weight/2;
  242.             e7 += weight - (weight/2);
  243.  
  244.             /* Crank out another pseudo random number... */
  245.             X = AA * (X % QQ) - RR * (LONG)(X / QQ);
  246.             if(X < 0)
  247.                 X += MM;
  248.  
  249.             /* Calculate the random weight. */
  250.             weight = X % max(1,min(e1,e3));
  251.  
  252.             /* Skew the small errors with the weight. */
  253.             e1 -=           weight/2;
  254.             e3 += weight - (weight/2);
  255.  
  256.             next[x+1] += e1;    /* 1 x error */
  257.             next[x-1] += e3;    /* 3 x error */
  258.             next[x  ] += e5;    /* 5 x error */
  259.             this[x+1] += e7;    /* 7 x error */
  260.         }
  261.     }
  262.  
  263.     dd->dd_Seed = X;
  264.  
  265.     /* Swap the dithering buffers and reset the buffer
  266.      * for the next line.
  267.      */
  268.     RotateDitherLines(dd);
  269. }
  270.  
  271. STATIC VOID
  272. TransferFloydSteinberg(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,DITHERDATA_T * dd)
  273. {
  274.     LONG x,threshold,error,err2;
  275.     SAMPLE_T * this = dd->dd_Lines[0];
  276.     SAMPLE_T * next = dd->dd_Lines[1];
  277.  
  278.     if(dd->dd_Reverse)
  279.     {
  280.         ColorInt += (width-1);
  281.  
  282.         for(x = width-1 ; x >= 0 ; x--)
  283.         {
  284.             /* Add the intensity (the greater the darker) and the error for
  285.              * the current line.
  286.              */
  287.             threshold = (this[x] / 16) + ColorInt->colorByte[component];
  288.  
  289.             /* Make sure that the resulting value is within
  290.              * valid bounds.
  291.              */
  292.             if(threshold < 0)
  293.                 threshold = 0;
  294.             else if (threshold > 255)
  295.                 threshold = 255;
  296.  
  297.             ColorInt--; /* bump ptr for next time */
  298.  
  299.             /* Now check if this pixel should come out black
  300.              * or white (0 = white, 255 = black).
  301.              */
  302.             if(threshold < 128)
  303.             {
  304.                 /* White pixel */
  305.                 error = threshold - 0;
  306.             }
  307.             else
  308.             {
  309.                 /* Black pixel */
  310.                 error = threshold - 255;
  311.  
  312.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  313.             }
  314.  
  315.             /* Now distribute the error. */
  316.             err2 = error + error;
  317.  
  318.                             next[x-1] += error;    /* 1 x error */
  319.             error += err2;    next[x+1] += error;    /* 3 x error */
  320.             error += err2;    next[x  ] += error;    /* 5 x error */
  321.             error += err2;    this[x-1] += error;    /* 7 x error */
  322.         }
  323.     }
  324.     else
  325.     {
  326.         for(x = 0 ; x < width ; x++)
  327.         {
  328.             /* Add the intensity (the greater the darker) and the error for
  329.              * the current line.
  330.              */
  331.             threshold = (this[x] / 16) + ColorInt->colorByte[component];
  332.  
  333.             /* Make sure that the resulting value is within
  334.              * valid bounds.
  335.              */
  336.             if(threshold < 0)
  337.                 threshold = 0;
  338.             else if (threshold > 255)
  339.                 threshold = 255;
  340.  
  341.             ColorInt++; /* bump ptr for next time */
  342.  
  343.             /* Now check if this pixel should come out black
  344.              * or white (0 = white, 255 = black).
  345.              */
  346.             if(threshold < 128)
  347.             {
  348.                 /* White pixel */
  349.                 error = threshold - 0;
  350.             }
  351.             else
  352.             {
  353.                 /* Black pixel */
  354.                 error = threshold - 255;
  355.  
  356.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  357.             }
  358.  
  359.             /* Now distribute the error. */
  360.             err2 = error + error;
  361.  
  362.                             next[x+1] += error;    /* 1 x error */
  363.             error += err2;    next[x-1] += error;    /* 3 x error */
  364.             error += err2;    next[x  ] += error;    /* 5 x error */
  365.             error += err2;    this[x+1] += error;    /* 7 x error */
  366.         }
  367.     }
  368.  
  369.     /* Swap the dithering buffers and reset the buffer
  370.      * for the next line.
  371.      */
  372.     RotateDitherLines(dd);
  373. }
  374.  
  375. STATIC VOID
  376. TransferStucki(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,DITHERDATA_T * dd)
  377. {
  378.     LONG x,threshold,error;
  379.     SAMPLE_T * l0 = dd->dd_Lines[0];
  380.     SAMPLE_T * l1 = dd->dd_Lines[1];
  381.     SAMPLE_T * l2 = dd->dd_Lines[2];
  382.  
  383.     if(dd->dd_Reverse)
  384.     {
  385.         ColorInt += (width-1);
  386.  
  387.         for(x = width-1 ; x >= 0 ; x--)
  388.         {
  389.             /* Add the intensity (the greater the darker) and the error for
  390.              * the current line.
  391.              */
  392.             threshold = (l0[x] / 42) + ColorInt->colorByte[component];
  393.  
  394.             /* Make sure that the resulting value is within
  395.              * valid bounds.
  396.              */
  397.             if(threshold < 0)
  398.                 threshold = 0;
  399.             else if (threshold > 255)
  400.                 threshold = 255;
  401.  
  402.             ColorInt--; /* bump ptr for next time */
  403.  
  404.             /* Now check if this pixel should come out black
  405.              * or white (0 = white, 255 = black).
  406.              */
  407.             if(threshold < 128)
  408.             {
  409.                 /* White pixel */
  410.                 error = threshold - 0;
  411.             }
  412.             else
  413.             {
  414.                 /* Black pixel */
  415.                 error = threshold - 255;
  416.  
  417.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  418.             }
  419.  
  420.             /* Now distribute the error. */
  421.  
  422.                             l2[x+2]    += error;    /* 1 x error */
  423.                             l2[x-2]    += error;    /* 1 x error */
  424.             error += error;    l2[x+1] += error;    /* 2 x error */
  425.                             l2[x-1] += error;    /* 2 x error */
  426.                             l1[x+2] += error;    /* 2 x error */
  427.                             l1[x-2] += error;    /* 2 x error */
  428.             error += error;    l2[x  ] += error;    /* 4 x error */
  429.                             l1[x+1] += error;    /* 4 x error */
  430.                             l1[x-1] += error;    /* 4 x error */
  431.                             l0[x-2] += error;    /* 4 x error */
  432.             error += error;    l1[x  ] += error;    /* 8 x error */
  433.                             l0[x-1] += error;    /* 8 x error */
  434.         }
  435.     }
  436.     else
  437.     {
  438.         for(x = 0 ; x < width ; x++)
  439.         {
  440.             /* Add the intensity (the greater the darker) and the error for
  441.              * the current line.
  442.              */
  443.             threshold = (l0[x] / 42) + ColorInt->colorByte[component];
  444.  
  445.             /* Make sure that the resulting value is within
  446.              * valid bounds.
  447.              */
  448.             if(threshold < 0)
  449.                 threshold = 0;
  450.             else if (threshold > 255)
  451.                 threshold = 255;
  452.  
  453.             ColorInt++; /* bump ptr for next time */
  454.  
  455.             /* Now check if this pixel should come out black
  456.              * or white (0 = white, 255 = black).
  457.              */
  458.             if(threshold < 128)
  459.             {
  460.                 /* White pixel */
  461.                 error = threshold - 0;
  462.             }
  463.             else
  464.             {
  465.                 /* Black pixel */
  466.                 error = threshold - 255;
  467.  
  468.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  469.             }
  470.  
  471.             /* Now distribute the error. */
  472.  
  473.                             l2[x-2]    += error;    /* 1 x error */
  474.                             l2[x+2]    += error;    /* 1 x error */
  475.             error += error;    l2[x-1] += error;    /* 2 x error */
  476.                             l2[x+1] += error;    /* 2 x error */
  477.                             l1[x-2] += error;    /* 2 x error */
  478.                             l1[x+2] += error;    /* 2 x error */
  479.             error += error;    l2[x  ] += error;    /* 4 x error */
  480.                             l1[x-1] += error;    /* 4 x error */
  481.                             l1[x+1] += error;    /* 4 x error */
  482.                             l0[x+2] += error;    /* 4 x error */
  483.             error += error;    l1[x  ] += error;    /* 8 x error */
  484.                             l0[x+1] += error;    /* 8 x error */
  485.         }
  486.     }
  487.  
  488.     /* Swap the dithering buffers and reset the buffer
  489.      * for the next line.
  490.      */
  491.     RotateDitherLines(dd);
  492. }
  493.  
  494. STATIC VOID
  495. TransferJarvisJudiceNinke(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,DITHERDATA_T * dd)
  496. {
  497.     LONG x,threshold,error,err2;
  498.     SAMPLE_T * l0 = dd->dd_Lines[0];
  499.     SAMPLE_T * l1 = dd->dd_Lines[1];
  500.     SAMPLE_T * l2 = dd->dd_Lines[2];
  501.  
  502.     if(dd->dd_Reverse)
  503.     {
  504.         ColorInt += (width-1);
  505.  
  506.         for(x = width-1 ; x >= 0 ; x--)
  507.         {
  508.             /* Add the intensity (the greater the darker) and the error for
  509.              * the current line.
  510.              */
  511.             threshold = (l0[x] / 48) + ColorInt->colorByte[component];
  512.  
  513.             /* Make sure that the resulting value is within
  514.              * valid bounds.
  515.              */
  516.             if(threshold < 0)
  517.                 threshold = 0;
  518.             else if (threshold > 255)
  519.                 threshold = 255;
  520.  
  521.             ColorInt--; /* bump ptr for next time */
  522.  
  523.             /* Now check if this pixel should come out black
  524.              * or white (0 = white, 255 = black).
  525.              */
  526.             if(threshold < 128)
  527.             {
  528.                 /* White pixel */
  529.                 error = threshold - 0;
  530.             }
  531.             else
  532.             {
  533.                 /* Black pixel */
  534.                 error = threshold - 255;
  535.  
  536.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  537.             }
  538.  
  539.             /* Now distribute the error. */
  540.             err2 = error + error;
  541.  
  542.                             l2[x+2]    += error;    /* 1 x error */
  543.                             l2[x-2]    += error;    /* 1 x error */
  544.             error += err2;    l2[x+1] += error;    /* 3 x error */
  545.                             l2[x-1] += error;    /* 3 x error */
  546.                             l1[x+2] += error;    /* 3 x error */
  547.                             l1[x-2] += error;    /* 3 x error */
  548.             error += err2;    l2[x  ] += error;    /* 5 x error */
  549.                             l1[x+1] += error;    /* 5 x error */
  550.                             l1[x-1] += error;    /* 5 x error */
  551.                             l0[x-2] += error;    /* 5 x error */
  552.             error += err2;    l1[x  ] += error;    /* 7 x error */
  553.                             l0[x-1] += error;    /* 7 x error */
  554.         }
  555.     }
  556.     else
  557.     {
  558.         for(x = 0 ; x < width ; x++)
  559.         {
  560.             /* Add the intensity (the greater the darker) and the error for
  561.              * the current line.
  562.              */
  563.             threshold = (l0[x] / 48) + ColorInt->colorByte[component];
  564.  
  565.             /* Make sure that the resulting value is within
  566.              * valid bounds.
  567.              */
  568.             if(threshold < 0)
  569.                 threshold = 0;
  570.             else if (threshold > 255)
  571.                 threshold = 255;
  572.  
  573.             ColorInt++; /* bump ptr for next time */
  574.  
  575.             /* Now check if this pixel should come out black
  576.              * or white (0 = white, 255 = black).
  577.              */
  578.             if(threshold < 128)
  579.             {
  580.                 /* White pixel */
  581.                 error = threshold - 0;
  582.             }
  583.             else
  584.             {
  585.                 /* Black pixel */
  586.                 error = threshold - 255;
  587.  
  588.                 ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  589.             }
  590.  
  591.             /* Now distribute the error. */
  592.             err2 = error + error;
  593.  
  594.                             l2[x-2]    += error;    /* 1 x error */
  595.                             l2[x+2]    += error;    /* 1 x error */
  596.             error += err2;    l2[x-1] += error;    /* 3 x error */
  597.                             l2[x+1] += error;    /* 3 x error */
  598.                             l1[x-2] += error;    /* 3 x error */
  599.                             l1[x+2] += error;    /* 3 x error */
  600.             error += err2;    l2[x  ] += error;    /* 5 x error */
  601.                             l1[x-1] += error;    /* 5 x error */
  602.                             l1[x+1] += error;    /* 5 x error */
  603.                             l0[x+2] += error;    /* 5 x error */
  604.             error += err2;    l1[x  ] += error;    /* 7 x error */
  605.                             l0[x+1] += error;    /* 7 x error */
  606.         }
  607.     }
  608.  
  609.     /* Swap the dithering buffers and reset the buffer
  610.      * for the next line.
  611.      */
  612.     RotateDitherLines(dd);
  613. }
  614.  
  615. /****************************************************************************/
  616.  
  617. STATIC VOID
  618. TransferBayer(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,LONG y)
  619. {
  620.     const int matrix_width    = 16;
  621.     const int matrix_height    = 16;
  622.  
  623.     STATIC const UBYTE BayerMatrix[16 * 16] =
  624.     {
  625.         0x01,0xEB,0x3B,0xDB,0x0F,0xE7,0x37,0xD7,0x02,0xE8,0x38,0xD8,0x0C,0xE4,0x34,0xD4,
  626.         0x81,0x41,0xBB,0x7B,0x8F,0x4F,0xB7,0x77,0x82,0x42,0xB8,0x78,0x8C,0x4C,0xB4,0x74,
  627.         0x21,0xC1,0x11,0xFB,0x2F,0xCF,0x1F,0xF7,0x22,0xC2,0x12,0xF8,0x2C,0xCC,0x1C,0xF4,
  628.         0xA1,0x61,0x91,0x51,0xAF,0x6F,0x9F,0x5F,0xA2,0x62,0x92,0x52,0xAC,0x6C,0x9C,0x5C,
  629.         0x09,0xE1,0x31,0xD1,0x05,0xEF,0x3F,0xDF,0x0A,0xE2,0x32,0xD2,0x06,0xEC,0x3C,0xDC,
  630.         0x89,0x49,0xB1,0x71,0x85,0x45,0xBF,0x7F,0x8A,0x4A,0xB2,0x72,0x86,0x46,0xBC,0x7C,
  631.         0x29,0xC9,0x19,0xF1,0x25,0xC5,0x15,0xFE,0x2A,0xCA,0x1A,0xF2,0x26,0xC6,0x16,0xFC,
  632.         0xA9,0x69,0x99,0x59,0xA5,0x65,0x95,0x55,0xAA,0x6A,0x9A,0x5A,0xA6,0x66,0x96,0x56,
  633.         0x03,0xE9,0x39,0xD9,0x0D,0xE5,0x35,0xD5,0x00,0xEA,0x3A,0xDA,0x0E,0xE6,0x36,0xD6,
  634.         0x83,0x43,0xB9,0x79,0x8D,0x4D,0xB5,0x75,0x80,0x40,0xBA,0x7A,0x8E,0x4E,0xB6,0x76,
  635.         0x23,0xC3,0x13,0xF9,0x2D,0xCD,0x1D,0xF5,0x20,0xC0,0x10,0xFA,0x2E,0xCE,0x1E,0xF6,
  636.         0xA3,0x63,0x93,0x53,0xAD,0x6D,0x9D,0x5D,0xA0,0x60,0x90,0x50,0xAE,0x6E,0x9E,0x5E,
  637.         0x0B,0xE3,0x33,0xD3,0x07,0xED,0x3D,0xDD,0x08,0xE0,0x30,0xD0,0x04,0xEE,0x3E,0xDE,
  638.         0x8B,0x4B,0xB3,0x73,0x87,0x47,0xBD,0x7D,0x88,0x48,0xB0,0x70,0x84,0x44,0xBE,0x7E,
  639.         0x2B,0xCB,0x1B,0xF3,0x27,0xC7,0x17,0xFD,0x28,0xC8,0x18,0xF0,0x24,0xC4,0x14,0xFE,
  640.         0xAB,0x6B,0x9B,0x5B,0xA7,0x67,0x97,0x57,0xA8,0x68,0x98,0x58,0xA4,0x64,0x94,0x54
  641.     };
  642.  
  643.     UBYTE const * const matrix_row = &BayerMatrix[(y % matrix_height) * matrix_width];
  644.     LONG x;
  645.  
  646.     for(x = 0 ; x < width ; x++)
  647.     {
  648.         /* Check if we should render Black */
  649.         if(ColorInt->colorByte[component] > matrix_row[x % matrix_width])
  650.             ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  651.  
  652.         ColorInt++; /* bump ptr for next time */
  653.     }
  654. }
  655.  
  656. STATIC VOID
  657. TransferHalftone(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,LONG y)
  658. {
  659.     const int matrix_width    = 8;
  660.     const int matrix_height    = 8;
  661.  
  662.     STATIC const UBYTE HalftoneMatrix[8 * 8] =
  663.     {
  664.         0x90,0xA0,0x98,0x80,0x6C,0x5C,0x64,0x7C,
  665.         0xD8,0xE0,0xE8,0xB0,0x24,0x1C,0x14,0x4C,
  666.         0xD0,0xF8,0xF0,0xA8,0x2C,0x04,0x0C,0x54,
  667.         0xB8,0xC8,0xC0,0x88,0x44,0x34,0x3C,0x74,
  668.         0x68,0x58,0x60,0x78,0x94,0xA4,0x9C,0x84,
  669.         0x20,0x18,0x10,0x48,0xDC,0xE4,0xEC,0xB4,
  670.         0x28,0x00,0x08,0x50,0xD4,0xFC,0xF4,0xAC,
  671.         0x40,0x30,0x38,0x70,0xBC,0xCC,0xC4,0x8C
  672.     };
  673.  
  674.     UBYTE const * const matrix_row = &HalftoneMatrix[(y % matrix_height) * matrix_width];
  675.     LONG x;
  676.  
  677.     for(x = 0 ; x < width ; x++)
  678.     {
  679.         /* Check if we should render Black */
  680.         if(ColorInt->colorByte[component] > matrix_row[x % matrix_width])
  681.             ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  682.  
  683.         ColorInt++; /* bump ptr for next time */
  684.     }
  685. }
  686.  
  687. STATIC VOID
  688. TransferThreshold(UBYTE * ptr,LONG width,union colorEntry *ColorInt,int component,UBYTE threshold)
  689. {
  690.     LONG x;
  691.  
  692.     for(x = 0 ; x < width ; x++)
  693.     {
  694.         /* Check if we should render Black */
  695.         if(ColorInt->colorByte[component] > threshold)
  696.             ptr[x / 8] |= (1 << (7 - (x % 8))); /* set bit */
  697.  
  698.         ColorInt++; /* bump ptr for next time */
  699.     }
  700. }
  701.  
  702. /****************************************************************************/
  703.  
  704. VOID
  705. Transfer(
  706.     struct PrtInfo *    PInfo,
  707.     union colorEntry *    ColorInt,        /* colour data to process */
  708.     LONG                y,                /* row # */
  709.     UBYTE *                ptr,            /* ptr to buffer */
  710.     DITHERDATA_T *        dd,                /* Auxiliary data for error dispersion dithering */
  711.     int                    component)        /* Which colour component */
  712. {
  713.     /* Are we thresholding? */
  714.     if(PInfo->pi_threshold > 0)
  715.     {
  716.         TransferThreshold(ptr,PInfo->pi_width,ColorInt,component,255 - PInfo->pi_threshold);
  717.     }
  718.     else
  719.     {
  720.         /* Ok, so we are dithering; which dithering technique is it? */
  721.         switch(PD->pd_Preferences.PrintFlags & DITHERING_MASK)
  722.         {
  723.             /* Ordered dithering using the Bayer matrix (256 shades of grey). */
  724.             case ORDERED_DITHERING:
  725.  
  726.                 TransferBayer(ptr,PInfo->pi_width,ColorInt,component,y);
  727.                 break;
  728.  
  729.             /* Ordered dithering using the halftone screen matrix (64 shades of grey). */
  730.             case HALFTONE_DITHERING:
  731.  
  732.                 TransferHalftone(ptr,PInfo->pi_width,ColorInt,component,y);
  733.                 break;
  734.  
  735.             /* Dithering with error dispersion using the Floyd-Steinberg filter (256 shades of grey). */
  736.             case FLOYD_DITHERING:
  737.  
  738.                 TransferFloydSteinberg(ptr,PInfo->pi_width,ColorInt,component,dd);
  739.             /*    TransferBlueNoise(ptr,PInfo->pi_width,ColorInt,component,dd);    */
  740.             /*    TransferStucki(ptr,PInfo->pi_width,ColorInt,component,dd);    */
  741.             /*    TransferJarvisJudiceNinke(ptr,PInfo->pi_width,ColorInt,component,dd);    */
  742.                 break;
  743.         }
  744.     }
  745. }
  746.